JavaでMySQLのデータベースにトランザクション処理
はじめに
前回の「JavaからMySQLに接続して登録する」ではSQL文を1つ1つコミットしていましたが、今回は複数のSQL文の登録とトランザクション処理を紹介します。 トランザクション処理を行うと、複数のSQL文の内の1つ以上でエラーが発生した場合に、その全ての処理を無かった事にしてくれます。
テーブル
こちらに登録します。
コード
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class ConnectionClass { static final String URL = "jdbc:mysql://localhost/cm"; static final String USERNAME = "user"; static final String PASSWORD = "pass"; public static void main(String[] args) { String sql = "INSERT INTO music VALUES (?, ?, ?, ?);"; String[][] list = { {"1", "Sam Smith", "Stay With Me", "2015"}, {"2", "Kanye West", "Gold Digger", "2005"}, {"3", "Roni Size", "It's A Jazz Thing", "1994"}, {"4", "Prince", "Kiss", "1988"}, {"5", "Led Zeppelin", "When The Levee Breaks", "1971"} }; try ( Connection connection = DriverManager.getConnection(URL,USERNAME,PASSWORD); PreparedStatement statement = connection.prepareStatement(sql); ) { connection.setAutoCommit(false); for (int i = 0; i < list.length; i++) { statement.setInt (1, Integer.valueOf(list[i][0])); statement.setString(2, list[i][1]); statement.setString(3, list[i][2]); statement.setInt (4, Integer.valueOf(list[i][3])); statement.addBatch(); System.out.println(statement.toString()); } int[] result = statement.executeBatch(); System.out.println("登録:" + result.length + "件"); try { connection.commit(); System.out.println("登録成功"); } catch (SQLException e) { connection.rollback(); System.out.println("登録失敗:ロールバック実行"); e.printStackTrace(); } } catch (SQLException e) { e.printStackTrace(); } } }
解説
動的に実行するためのSQL文を定義。 値を当てはめる箇所を "?" と記述します。
String sql = "INSERT INTO music VALUES (?, ?, ?, ?);";
SQL文に当てはめる値の配列。
String[][] list = { {"1", "Sam Smith", "Stay With Me", "2015"}, {"2", "Kanye West", "Gold Digger", "2005"}, {"3", "Roni Size", "It's A Jazz Thing", "1994"}, {"4", "Prince", "Kiss", "1988"}, {"5", "Led Zeppelin", "When The Levee Breaks", "1971"} };
SQL文をデータベースに送るオブジェクトを生成。 Statement と違い、ここで仮のSQL文も設定します。
PreparedStatement statement = connection.prepareStatement(sql); ) {
トランザクション処理には複数のSQL文をまとめてコミットを行う必要が有るので、自動コミット機能をオフにします。
connection.setAutoCommit(false);
配列の要素をSQL文に設定します。 setInt() で整数、 setString() で文字列に置き換えられます。 第1引数:”?”の何個目か 第2引数:置き換える値
statement.setInt (1, Integer.valueOf(list[i][0])); statement.setString(2, list[i][1]); statement.setString(3, list[i][2]); statement.setInt (4, Integer.valueOf(list[i][3]));
addBatch() でSQL文をバッチ登録。 確認のために statement.toString() でSQL文などを標準出力します。
statement.addBatch(); System.out.println(statement.toString());
バッチ登録した複数のSQL文をバッチ処理します。 その返り値は int型 の配列で、更新した回数が要素数になります。
int[] result = statement.executeBatch();
データベースに登録します。
connection.commit();
データベースの登録でエラーが発生したらロールバック処理ですべての変更を取り消します。
connection.rollback();
標準出力結果
com.mysql.jdbc.JDBC4PreparedStatement@22d8cfe0: INSERT INTO music VALUES (1, 'Sam Smith', 'Stay With Me', 2015); com.mysql.jdbc.JDBC4PreparedStatement@22d8cfe0: INSERT INTO music VALUES (2, 'Kanye West', 'Gold Digger', 2005); com.mysql.jdbc.JDBC4PreparedStatement@22d8cfe0: INSERT INTO music VALUES (3, 'Roni Size', 'It\'s A Jazz Thing', 1994); com.mysql.jdbc.JDBC4PreparedStatement@22d8cfe0: INSERT INTO music VALUES (4, 'Prince', 'Kiss', 1988); com.mysql.jdbc.JDBC4PreparedStatement@22d8cfe0: INSERT INTO music VALUES (5, 'Led Zeppelin', 'When The Levee Breaks', 1971); 登録:5件 登録成功
データベースの状態
まとめ
PreparedStatement を使う事は便利なだけではなくSQLインジェクション対策になるので、Statement よりこちらを使う方が良いです。